import Rte from 'editor/index'
import { RteCommandProp } from 'editor/command/declate'
import { ElementListener, Refs, RenderInst } from 'share/declare'
import { htmlToElement } from 'share/utils'
import render from 'share/render'

import ast from '!!html-ast-loader!./droplist.html'
import { DroplistMenuConfig, MenuType, SelectionMenuConfig } from 'menu/declare'

export interface DroplistMenuRefs extends Refs {
  root: HTMLDivElement
  currIcon: HTMLSpanElement
  optionRoot: HTMLUListElement
}

export default class DroplistMenu implements RenderInst {
  // @ts-ignore
  public $refs: DroplistMenuRefs = {}

  public $listener: ElementListener<DroplistMenu> = {
    hidebar() {
      this.editor.$moniter.$emit('hidebar', null)
    },
    commandCurrent() {
      this.run()
    },
    openList() {
      if (this.editor.$data.contenteditable) {
        const { optionRoot } = this.$refs
        optionRoot.style.setProperty('display', 'block')
        // 注册隐藏监听
        this.editor.$moniter.$once('hidebar', function () {
          optionRoot.style.setProperty('display', 'none')
        })
      }
    },
  }

  public type: MenuType = MenuType.DROPLIST

  // @ts-ignore
  public command: RteCommandProp

  // @ts-ignore
  public current: RteCommandProp | string

  public constructor(public editor: Rte, config: DroplistMenuConfig | SelectionMenuConfig) {
    render(ast, this)

    const { currIcon, optionRoot } = this.$refs

    editor.$data.$on('height', (nv) => {
      if (typeof nv === 'string') {
        optionRoot.style.setProperty('max-height', nv)
      } else {
        optionRoot.style.removeProperty('max-height')
      }
    })

    // 一个下拉选项对应一个命令
    if (config.type === MenuType.DROPLIST) {
      const { options } = config as DroplistMenuConfig

      this.type = MenuType.DROPLIST
      this.command = this.current = options[0][0]
      currIcon.setAttribute('class', `rtei ${editor.icon[this.command]}`)

      // 生成 droplist options
      options.forEach(([command, label]) => {
        const icon = editor.icon[command]

        const dom = htmlToElement(`
      <li class="rte-toolbar__select-option">
        <span class="rtei ${icon}"></span>
        <span class="rte-toolbar__select-option-label">${label}</span>
      </li>`)

        dom.addEventListener('click', () => {
          currIcon.setAttribute('class', `rtei ${icon}`)
          this.command = this.current = command
          this.editor.$moniter.$emit('hidebar', null)
          // 执行 command 命令
          this.run()
        })

        optionRoot.appendChild(dom)
      })
      return this
    }

    // 一个下拉选项对应命令的一个值
    if (config.type === MenuType.SELECTION) {
      const { command, options, icon } = config as SelectionMenuConfig

      this.type = MenuType.SELECTION
      this.command = this.current = command
      if (icon) {
        currIcon.setAttribute('class', `rtei ${editor.icon[command]}`)
      } else {
        currIcon.innerText = this.current = options[0]
      }

      options.forEach((value) => {
        const dom = htmlToElement(`
        <li class="rte-toolbar__select-option">
          <span class="rtei"></span>
          <span class="rte-toolbar__select-option-label">${value}</span>
        </li>`)

        dom.addEventListener('click', () => {
          this.current = value
          editor.$moniter.$emit('hidebar', null)
          if (!icon) {
            currIcon.innerText = value
          }
          // 执行 command 命令
          this.run()
        })

        optionRoot.appendChild(dom)
      })

      return this
    }

    throw new Error(`DroplistMenu 只支持 MenuType 为 ${MenuType.SELECTION} 和 ${MenuType.DROPLIST} 两种参数的配置`)
  }

  public run() {
    console.log({ type: this.type, command: this.command, current: this.current })
  }
}
